
import { AcGameObject } from "./AcGameObject";
import { Enemy } from "./Enemy";
import { Wall } from "./Wall";
import { Tank } from "./Tank";


export class GameMap extends AcGameObject {
    constructor(ctx, parent,store) {//全局变量当成参数传入
        super();//无效参数，因为这里用不到这些参数，但是js里面好像只能有一个构造函数

        this.ctx = ctx;
        this.parent = parent;
        this.store = store;
        this.L = 0;//每一个单元正方体的边长
        this.rows = 21;
        this.cols = 20;

        this.inner_walls_count = 100;
        this.inner_enemy_count = 14;
        this.inner_iron_wall_count = 50;
        this.walls = [];//木头墙,铁墙都在里面
        // this.iron_walls = [];//铁墙
        this.enemys = [];//enemys一直在动，不需要启动特判，只要看有没有撞就行
        this.player = null;//暂时唯一一个玩家

        this.bullets = [];
        this.house = null;
    }


    crete_walls() {
        let g = [];//地图数组
        for (let r = 0; r < this.rows; r ++ ) {
            g[r] = [];
            for (let c = 0; c < this.cols; c ++ ) {
                g[r][c] = false;
            }
        }
        for (let i = 0; i < this.inner_walls_count+this.inner_iron_wall_count; i++) {//画出所有墙（加上铁墙）
            while (i>=0) {//死循环
                let r=parseInt(Math.random()*this.rows);
                let c=parseInt(Math.random()*this.cols);

                //随机生成一个位置
                if(g[r][c] || r==0)continue;//暂时第一行不生成墙，专门用来生成敌机
                if(r==this.rows-1 && c==0)continue;//左下角暂时只生成玩家
                g[r][c]=true;
                if(i<this.inner_walls_count)this.walls.push(new Wall(r, c,"wood",this));//创造木头墙（仍然用常规坐标）
                else    this.walls.push(new Wall(r,c,"iron",this))
                break;
            }
          }
        return true;
    }


    add_listening_events() {
        this.ctx.canvas.focus();
        let current_player =this.player;
        if(current_player===null)return ;

        this.ctx.canvas.addEventListener("keydown", e => {
            if( current_player.status!=="die"){
                if (e.key === 'w') {current_player.set_status("move");current_player.set_direction(0);}
                else if (e.key === 'd'){current_player.set_status("move"); current_player.set_direction(1);}
                else if (e.key === 's') {current_player.set_status("move");current_player.set_direction(2);}
                else if (e.key === 'a') {current_player.set_status("move");current_player.set_direction(3);}
                else if (e.key === ' '){
                    current_player.attack();//当前玩家射击时，需要给后端发送射击操作信息，并送给其他页面玩家做页面同步
                }
            }
        });
        this.ctx.canvas.addEventListener("keyup", function() {
            if(current_player.status!=="die"){
                current_player.set_status("idle");//不设置keyup，坦克会一直走
            }
        });
    }



    crete_enemys(){//
        let g_enemys = [];//地图第一行的列数
        for(let i=0;i<this.cols;i++)g_enemys[i]=false;//初始化

        for(let i=0;i< this.inner_enemy_count;i++){
            while(i>=0){
                let c=parseInt(Math.random()*(this.cols));
                if(g_enemys[c])continue;
                // let direction = parseInt(Math.random()*4);
                g_enemys[c]=true;
                this.enemys.push(new Enemy(0,c,"ai",this));//转成canvas格子单位坐标（后续要转像素），在第零行的一个随机不重复位置生成一个敌机
                
                break;
            }
        }
    }

    creat_player(){
        this.player = new Tank(this.rows-1,0,"player",this,this.store);
    }


    update_size() {
        this.L = parseInt(Math.min(this.parent.clientWidth / this.cols, this.parent.clientHeight / this.rows));
        this.ctx.canvas.width = this.L * this.cols;
        this.ctx.canvas.height = this.L * this.rows;
    }

    check_boundary_cross(cell){ // 检测当前坦克位置是否出界了
        if(cell.r<0 || cell.r>this.rows-cell.height || cell.c<0 || cell.c>this.cols-cell.width)return true;
        //注意：：这里加入height和width是为了使得坦克能够到达底部
        return false;
    }

    check_player_hit(cell){ // 检测玩家是否被打中（具体被谁的子弹打中，在Bullet.js页面判断），被打中，就返回玩家

        let player = this.player;
            if(this.check_overlay(cell,player.cell) ){//只判当前位置
                return player;
            }
        return null;
    }


    check_ai_hit(cell){ // 检测ai是否被打中（具体被谁的子弹打中，在Bullet.js页面判断）就返回这个ai
        //被玩家打中，才要删除这名ai，但是这里并不知道子弹的主人，所以要在Bullet实现可能存在的删除操作
        for(let enemy of this.enemys){//以当前坦克的下一步位置为基准，和其他坦克的当前位置和下一步位置去判断
            if(this.check_overlay(cell,enemy.cell)){

                return enemy;
            }
        }
        return null;
    }
    check_wall_hit(cell){ // 检测当前坦克的下一步位置是否撞墙了，如果撞了，就返回这个墙，并从墙列表中删除，否则返回空
        for (let wall of this.walls) {
            if(wall.status==="idle")//因为死墙没有摧毁，没有从列表删除，所以要判断
                if (this.check_overlay(cell,wall)){//这里因为wall本身可以看成是Cell类
                    return wall;//表示撞实了,返回墙，要在子弹类里面进行撞之后的操作，因为这是一个复用的类，坦克撞墙也调用了
                }
        }
        return null;
    }

    check_bullet_hit(cell){//检测子弹被另一阵营子弹撞了(在子弹类中判断)
        for(let bullet of this.bullets){
            if(this.check_overlay(cell,bullet.cell))
                return bullet;
        }
        return null;
    }
    
    check_overlay(A,B){//检测AB有没有碰在一起（只要AB有x,y,width,height参数，就能进来比较）
        //(先判断没碰着时的情况，然后再取反)
        //依次是：A左B右，B左A右，A上B下，A下B上
        let state = (A.c + A.width) < (B.c)
        ||(A.c) >( B.c + B.width) ||
        (A.r + A.height) < (B.r) ||
        (A.r) > (B.r + B.height);
        return !state;//取反
    }
    

    check_valid(cell,tank_kind) {  // 检测当前坦克位置是否合法
        let player = this.player;
        if(this.check_boundary_cross(cell))return false;

        if(this.check_wall_hit(cell))return false;


        if(tank_kind && tank_kind.substring(0,6) === "player"){//玩家碰ai
            for(let enemy of this.enemys){//以当前坦克的下一步位置为基准，和其他坦克的当前位置和下一步位置去判断
                if(this.check_overlay(cell,enemy.cell)){
                    return false;
                }
            }

        }else{//ai碰玩家
            if(this.check_overlay(cell,player.cell) ){//只判当前位置
                return false;
            }
        }
        return true;
    }


    start() {
        this.update_size();//每次都要更新大小，因为窗口可能在不断缩小放大
        this.crete_walls();//因为创建墙，要用到this.L，所以this.update_size();要在前面执行一次；
        this.crete_enemys();
        this.creat_player();
        this.add_listening_events();
    }
    update() {
        this.update_size();//每次都要更新大小，因为窗口可能在不断缩小放大
        // for (const enemy of this.enemys) {//一定要对每个坦克单独判断并设置方向
        //     if(enemy.set_direction_auto()){
        //         enemy.next_step();
        //     }
        // }

        this.render();
    }

    render() {
        const color_even = "#AAD752", color_odd = "#A2D048";
        for (let r = 0; r < this.rows; r++) {
            for (let c = 0; c < this.cols; c++) {
                if ((r + c) % 2 == 0) {
                    this.ctx.fillStyle = color_even;
                } else {
                    this.ctx.fillStyle = color_odd;
                }
                this.ctx.fillRect(c * this.L, r * this.L, this.L, this.L);
            }
        }
    }


}
